package com.ly.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ly.common.core.bean.R;
import com.ly.common.core.bean.vo.SysMessageTypeVO;
import com.ly.common.core.constant.BaseConstant;
import com.ly.common.core.enums.SysMsgTypeEnum;
import com.ly.common.core.utils.BaseUtils;
import com.ly.system.system.bean.dto.SysMessageDTO;
import com.ly.system.system.bean.entity.SysMessage;
import com.ly.system.system.bean.entity.SysMessageSend;
import com.ly.system.system.bean.entity.SysUser;
import com.ly.system.system.bean.vo.SysMessageVO;
import com.ly.system.mapper.SysMessageMapper;
import com.ly.system.service.ISysMessageSendService;
import com.ly.system.service.ISysMessageService;
import com.ly.system.service.ISysUserService;
import com.ly.system.util.XssUtils;
import com.ly.test.enums.RangeDateEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * 系统通告表
 *
 * @author jeecg
 * @Date: 2019-01-02
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMessage> implements ISysMessageService {

    private final ISysUserService sysUserService;
    private final ISysMessageSendService sysMessageSendService;
    // 线程池
    private final ThreadPoolExecutor executor;

    @Override
    public R getId(String id) {
        SysMessage entity = this.getById(id);
        if (entity == null) {
            return R.fail("未找到对应数据");
        }
        return R.ok(entity);
    }

    @Override
    public R getPage(SysMessage entity, Page<SysMessage> page) {
        IPage<SysMessage> pageList = this.page(
                page,
                new LambdaQueryWrapper<SysMessage>()
                        .like(StrUtil.isNotBlank(entity.getTitle()), SysMessage::getTitle, entity.getTitle())
                        .orderByDesc(SysMessage::getCreateTime)
        );
        return R.ok(pageList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R add(SysMessage entity) {
        entity.setSendStatus(BaseConstant.MSG_SEND_STATUS_0);
        boolean flag = this.save(entity);
        if (!entity.getMsgType().equals(BaseConstant.MSG_TYPE_ALL)) {
            // 1.插入通告表记录
            // 2.插入用户通告阅读标记表记录
            String userId = entity.getUserIds();
            List<String> userIds = StrUtil.split(userId, ",", true, true);
            String messageId = entity.getId();
            Date refDate = new Date();
            for (int i = 0; i < userIds.size(); i++) {
                SysMessageSend send = new SysMessageSend();
                send.setMessageId(messageId);
                send.setUserId(userIds.get(i));
                send.setReadFlag(BaseConstant.MSG_READ_FLAG_0);
                send.setReadTime(refDate);
                sysMessageSendService.save(send);
            }
        }
        return flag ? R.ok(true, "创建成功") : R.fail("创建失败");
    }

    /**
     * @功能：编辑消息信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R edit(SysMessage entity) {
        entity.setTitle(XssUtils.scriptXss(entity.getTitle()));
        // 1.更新系统信息表数据
        boolean flag = this.updateById(entity);
        String userId = entity.getUserIds();
        if (StrUtil.isNotEmpty(userId) && entity.getMsgType().equals(BaseConstant.MSG_TYPE_UESR)) {
            // 2.补充新的通知用户数据
            List<String> userIds = StrUtil.split(userId, ",", true, true);
            String messageId = entity.getId();
            Date refDate = new Date();
            for (int i = 0; i < userIds.size(); i++) {
                List<SysMessageSend> sendList = sysMessageSendService.list(
                        new LambdaQueryWrapper<SysMessageSend>()
                                .eq(SysMessageSend::getMessageId, messageId)
                                .eq(SysMessageSend::getUserId, userIds.get(i))
                );
                if (sendList.size() <= 0) {
                    SysMessageSend send = new SysMessageSend();
                    send.setMessageId(messageId);
                    send.setUserId(userIds.get(i));
                    send.setReadFlag(BaseConstant.MSG_READ_FLAG_0);
                    send.setReadTime(refDate);
                    sysMessageSendService.save(send);
                }
            }
            // 3. 删除多余通知用户数据
            sysMessageSendService.remove(
                    new LambdaQueryWrapper<SysMessageSend>()
                            .notIn(SysMessageSend::getUserId, userIds)
                            .eq(SysMessageSend::getMessageId, messageId)
            );
        }
        return flag ? R.ok(true, "修改成功") : R.fail("修改失败");
    }

    @Override
    public R delete(String id) {
        boolean flag = this.removeById(id);
        return flag ? R.ok(true, "删除成功") : R.fail("删除失败");
    }

    @Override
    public R deleteBatch(String ids) {
        boolean flag = this.removeByIds(Arrays.asList(ids.split(",")));
        return flag ? R.ok(true, "批量删除成功") : R.fail("批量删除失败");
    }

    @Override
    public R editMsgSend(SysMessageSend entity) {
        boolean flag = sysMessageSendService.updateById(entity);
        return flag ? R.ok(true, "修改成功") : R.fail("修改失败");
    }

    @Override
    public void batchInsertSysAnnouncementSend(String messageId, Integer tenantId) {
        if (BaseConstant.TENANT_FLAG && tenantId != null) {
            log.info("补全公告与用户的关系数据，租户ID = {}", tenantId);
        } else {
            tenantId = null;
        }
        List<SysUser> userList = sysUserService.list(
                new LambdaQueryWrapper<SysUser>()
                        .eq(ObjUtil.isNotNull(tenantId), SysUser::getTenantId, tenantId)
        );
        List<String> userIdList = userList.stream().map(n -> n.getId()).collect(Collectors.toList());
        List<SysMessageSend> sendList = new ArrayList<>();
        if (CollUtil.isNotEmpty(userIdList)) {
            for (String userId : userIdList) {
                SysMessageSend send = new SysMessageSend();
                send.setMessageId(messageId);
                send.setUserId(userId);
                send.setReadFlag(BaseConstant.MSG_READ_FLAG_0);
                sendList.add(send);
            }
            log.info("补全公告与用户的关系数据，sendList size = {}", sendList.size());
            sysMessageSendService.saveBatch(sendList);
        }
    }

    @Override
    public R getMsgSend(String id) {
        return sysMessageSendService.getId(id);
    }

    @Override
    public R getMessageGroupCount() {
        String userId = BaseUtils.getId();
        // 获取上个月的第一天（只查近两个月的通知）
        String beginDate = DateUtil.beginOfMonth(DateUtil.lastMonth()).toString();
        List<SysMessageSend> list = sysMessageSendService.list(
                new LambdaQueryWrapper<SysMessageSend>()
                        .eq(SysMessageSend::getUserId, userId)
                        .eq(SysMessageSend::getReadFlag, BaseConstant.MSG_READ_FLAG_0)
                        .ge(SysMessageSend::getCreateTime, beginDate)
        );
        List<SysMessageTypeVO> vos = SysMsgTypeEnum.getMessageType();
        Map<String, Long> map = list.stream().collect(Collectors.groupingBy(
                        n -> n.getMsgCategory(),          // 键：单词本身
                        Collectors.counting()             // 值：计数
                )
        );
        // 填充对应的数量
        vos.stream().forEach(n -> {
            Long count = map.get(n.getMsgCategory());
            count = count == null ? 0l : count;
            n.setCount(count);
        });
        return R.ok(vos);
    }

    @Override
    public R getMessagePage(Page<SysMessageVO> page, SysMessageDTO dto) {
        String rangeDateKey = dto.getRangeDateKey();
        if (StrUtil.isNotEmpty(rangeDateKey) && !RangeDateEnum.ZDY.getKey().equals(rangeDateKey)) {
            // 日期段落查询
            Map<String, String> map = RangeDateEnum.getRangeArray(rangeDateKey);
            if (map != null) {
                dto.setBeginDate(map.get("start"));
                dto.setEndDate(map.get("end"));
            }
        } else {
            // 处理时间格式
            if (StrUtil.isNotEmpty(dto.getBeginDate())) {
                dto.setBeginDate(dto.getBeginDate() + " 00:00:00");
            }
            if (StrUtil.isNotEmpty(dto.getEndDate())) {
                dto.setEndDate(dto.getEndDate() + " 23:59:59");
            }
        }
        // 管理员查看所有
        String userId = BaseUtils.getId();
        if (!BaseUtils.checkIsAdmin() || ObjUtil.isNotNull(dto.getAuthFlag())) {
            dto.setUserId(userId);
        }
        dto.setReadFlagSort("1");
        IPage<SysMessageVO> pageList = baseMapper.getMessagePage(page, dto);
        List<SysMessageVO> list = pageList.getRecords();
        // 3、设置当前页的消息为已读
        // if (CollUtil.isNotEmpty(list)) {
        //     // 设置已读
        //     List<String> idList = list.stream().map(item -> item.getId()).collect(Collectors.toList());
        //     sysMessageSendService.update(
        //             new LambdaUpdateWrapper<SysMessageSend>()
        //                     .set(SysMessageSend::getReadFlag, BaseConstant.MSG_READ_FLAG_1)
        //                     .in(SysMessageSend::getMessageId, idList)
        //                     .eq(SysMessageSend::getReadFlag, BaseConstant.MSG_READ_FLAG_0)
        //     );
        // }
        return R.ok(pageList);
    }

    @Override
    public R updateReadStatusMessage(SysMessageDTO dto) {
        String messageId = dto.getId();
        String userId = BaseUtils.getId();
        sysMessageSendService.update(
                new LambdaUpdateWrapper<SysMessageSend>()
                        .set(SysMessageSend::getReadFlag, BaseConstant.MSG_READ_FLAG_1)
                        .set(SysMessageSend::getReadTime, new Date())
                        .eq(SysMessageSend::getMessageId, messageId)
                        .eq(SysMessageSend::getUserId, userId)
        );
        return R.ok();
    }

    @Override
    public R updateAllUnreadMessage() {
        sysMessageSendService.update(
                new LambdaUpdateWrapper<SysMessageSend>()
                        .set(SysMessageSend::getReadFlag, BaseConstant.MSG_READ_FLAG_1)
                        .set(SysMessageSend::getReadTime, new Date())
                        .eq(SysMessageSend::getUserId, BaseUtils.getId())
                // .eq(SysMessageSend::getReadFlag, BaseConstant.MSG_READ_FLAG_0)
        );
        return R.ok(true, "清除未读消息成功");
    }

    @Override
    public R revokeMsg(String id) {
        SysMessage sysMessage = this.getById(id);
        if (sysMessage == null) {
            return R.fail("未找到对应实体");
        }
        this.update(
                new LambdaUpdateWrapper<SysMessage>()
                        .set(SysMessage::getSendStatus, BaseConstant.MSG_SEND_STATUS_2)
                        .set(SysMessage::getCancelTime, new Date())
                        .eq(SysMessage::getId, id)
        );
        return R.ok("操作成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R releaseMsg(String id) {
        SysMessage entity = this.getById(id);
        if (entity == null) {
            return R.fail("未找到对应实体");
        }
        boolean ok = this.update(
                new LambdaUpdateWrapper<SysMessage>()
                        .set(SysMessage::getSendStatus, BaseConstant.MSG_SEND_STATUS_1)
                        .set(SysMessage::getSendTime, new Date())
                        .set(SysMessage::getSender, BaseUtils.getRealname())
                        .eq(SysMessage::getId, id)
        );
        if (ok) {
            if (entity.getMsgType().equals(BaseConstant.MSG_TYPE_ALL)) {
                // 补全公告和用户之前的关系
                this.batchInsertSysAnnouncementSend(entity.getId(), entity.getTenantId());
            }
        }
        return R.ok("系统通知推送成功");
    }
}
